package model

import (
	"encoding/json"
	"errors"
	"fmt"
	"github.com/gomodule/redigo/redis"
	"go-web-learning/src/02_message_system/02_message_system/chatroom/common/message"
	"strconv"
)

// 服务器启动后就初始化一个UserDao实例，并做成全局变量

var MyUserDao *UserDao

// UserDao 完成对User结构体的操作，增删改查
type UserDao struct {
	redisPool *redis.Pool
}

// NewUserDao 使用工厂模式，获取到一个UserDao的实例
func NewUserDao(pool *redis.Pool) *UserDao {
	return &UserDao{pool}
}

// 根据用户id获取用户信息
func (dao *UserDao) getUserById(conn redis.Conn, id int) (user *message.User, err error) {
	// 通过给定的id，去redis查询这个用户
	userStr, err := redis.String(conn.Do("HGET", "users", id))
	if err != nil {
		if errors.Is(err, redis.ErrNil) {
			err = ERROR_USER_NOT_EXISTS
		}
		return
	}
	user = &message.User{}
	err = json.Unmarshal([]byte(userStr), user)
	if err != nil {
		fmt.Println("json反序列化出错")
		return
	}
	return
}

// Login 校验登陆
func (dao *UserDao) Login(id int, pwd string) (user *message.User, err error) {
	// 1、取出连接
	conn := dao.redisPool.Get()
	defer conn.Close()
	user, err = dao.getUserById(conn, id)
	if err != nil {
		return
	}
	if pwd != user.UserPwd {
		err = ERROR_USER_PWD_ERR
		return nil, err
	}
	user.UserPwd = ""
	return
}

// Register 注册
func (dao *UserDao) Register(id int, pwd, name string) (user *message.User, err error) {
	// 1、取出连接
	conn := dao.redisPool.Get()
	defer conn.Close()
	user, err = dao.getUserById(conn, id)
	// 只有报不存在的异常时，才继续注册
	if !errors.Is(err, ERROR_USER_NOT_EXISTS) {
		if err == nil {
			err = ERROR_USER_EXISTS
		}
		return
	}
	// 注册
	user = &message.User{
		UserId:   id,
		UserPwd:  pwd,
		UserName: name,
	}
	data, err := json.Marshal(user)
	if err != nil {
		return
	}
	_, err = conn.Do("HSET", "users", id, string(data))
	if err != nil {
		return
	}
	return
}

func (dao *UserDao) GetAllUsers() (userMap map[int]string) {
	// 1、取出连接
	conn := dao.redisPool.Get()
	defer conn.Close()
	userMap = make(map[int]string, 1024)
	data, err := redis.Strings(conn.Do("HGETALL", "users"))
	if err != nil {
		return
	}
	userId := -1
	for index, value := range data {
		if index%2 == 0 {
			id, err := strconv.Atoi(value)
			if err == nil {
				userId = id
			}
		} else {
			user := message.User{}
			err = json.Unmarshal([]byte(value), &user)
			if err == nil && userId > 0 {
				userMap[userId] = user.UserName
			}
		}
	}
	return
}
